import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:flutter/foundation.dart';

import '../../app/constants/api_constants.dart';
import '../../app/constants/app_constants.dart';
import '../../app/constants/enums/api_status.dart';
import '../../app/data/models/response/api_response.dart';
import '../../config/flavor_config.dart';
import '../errors/exceptions.dart';
import '../errors/error_handler.dart';
import '../../app/services/storage/secure_storage_service.dart';
import 'request_modifiers/auth_modifier.dart';
import 'request_modifiers/logger_modifier.dart';
import 'request_modifiers/error_modifier.dart';
import 'request_modifiers/cache_modifier.dart';

/// API提供者 - 基于GetConnect实现的HTTP客户端
class ApiProvider extends GetConnect {
  final GetStorage _storage = Get.find<GetStorage>();
  final SecureStorageService _secureStorage = Get.find<SecureStorageService>();
  final ErrorHandler _errorHandler = Get.find<ErrorHandler>();
  
  @override
  void onInit() {
    // 设置基础URL
    httpClient.baseUrl = FlavorConfig.to.config.apiBaseUrl;
    
    // 设置超时时间
    httpClient.timeout = const Duration(
      milliseconds: ApiConstants.connectionTimeout,
    );
    
    // 添加请求修改器(类似于拦截器)
    _addRequestModifiers();
    
    super.onInit();
  }
  
  /// 添加请求修改器
  void _addRequestModifiers() {
    // 认证请求修改器
    httpClient.addRequestModifier(AuthModifier(_storage).requestModifier);
    
    // 启用日志记录
    if (FlavorConfig.to.config.enableLogging) {
      httpClient.addRequestModifier(LoggerModifier().requestModifier);
      httpClient.addResponseModifier(LoggerModifier().responseModifier);
    }
    
    // 错误处理修改器
    httpClient.addResponseModifier(ErrorModifier().responseModifier);
    httpClient.addResponseModifier(cacheResponseModifier);
  }
  
  /// 获取认证Token
  String? _getToken() {
    return _storage.read<String>(AppConstants.tokenKey);
  }
  
  /// 创建通用请求头
  Map<String, String> _headers({Map<String, String>? customHeaders}) {
    // 基础请求头
    final Map<String, String> headers = {
      ApiConstants.contentType: ApiConstants.applicationJson,
      ApiConstants.accept: ApiConstants.applicationJson,
    };
    
    // 添加认证令牌
    final token = _getToken();
    if (token != null && token.isNotEmpty) {
      headers[ApiConstants.authorization] = '${ApiConstants.bearer} $token';
    }
    
    // 合并自定义请求头
    if (customHeaders != null) {
      headers.addAll(customHeaders);
    }
    
    return headers;
  }

  /// GET请求
  Future<ApiResponse<T>> get<T>(
    String url, {
    Map<String, dynamic>? query,
    Map<String, String>? headers,
    bool requiresAuth = true,
    String? cacheKey,
    Duration? cacheTimeout,
    bool refreshCache = false,
  }) async {
    try {
      final Map<String, dynamic> queryParameters = query ?? {};
      final Map<String, String> headersMap = _headers(customHeaders: headers);
      
      if (cacheKey != null) {
        headersMap['cache-key'] = cacheKey;
        
        if (cacheTimeout != null) {
          headersMap['cache-timeout'] = cacheTimeout.inSeconds.toString();
        }
        
        if (refreshCache) {
          headersMap['refresh-cache'] = 'true';
        }
      }
      
      final response = await httpClient.get(
        url,
        query: queryParameters,
        headers: headersMap,
      );
      
      return _handleResponse<T>(response);
    } on TimeoutException {
      return ApiResponse.error(
        status: ApiStatus.timeout,
        message: '请求超时',
      );
    } on SocketException {
      return ApiResponse.error(
        status: ApiStatus.noConnection,
        message: '网络连接错误',
      );
    } catch (e) {
      return ApiResponse.error(
        status: ApiStatus.failed,
        message: e.toString(),
      );
    }
  }

  /// POST请求
  Future<ApiResponse<T>> post<T>(
    String url, {
    dynamic body,
    Map<String, dynamic>? query,
    Map<String, String>? headers,
    bool requiresAuth = true,
    String? contentType,
  }) async {
    try {
      final response = await httpClient.post(
        url,
        body: body,
        query: query,
        headers: _headers(customHeaders: headers),
        contentType: contentType,
      );
      
      return _handleResponse<T>(response);
    } on TimeoutException {
      return ApiResponse.error(
        status: ApiStatus.timeout,
        message: '请求超时',
      );
    } on SocketException {
      return ApiResponse.error(
        status: ApiStatus.noConnection,
        message: '网络连接错误',
      );
    } catch (e) {
      return ApiResponse.error(
        status: ApiStatus.failed,
        message: e.toString(),
      );
    }
  }

  /// PUT请求
  Future<ApiResponse<T>> put<T>(
    String url, {
    dynamic body,
    Map<String, dynamic>? query,
    Map<String, String>? headers,
    bool requiresAuth = true,
    String? contentType,
  }) async {
    try {
      final response = await httpClient.put(
        url,
        body: body,
        query: query,
        headers: _headers(customHeaders: headers),
        contentType: contentType,
      );
      
      return _handleResponse<T>(response);
    } on TimeoutException {
      return ApiResponse.error(
        status: ApiStatus.timeout,
        message: '请求超时',
      );
    } on SocketException {
      return ApiResponse.error(
        status: ApiStatus.noConnection,
        message: '网络连接错误',
      );
    } catch (e) {
      return ApiResponse.error(
        status: ApiStatus.failed,
        message: e.toString(),
      );
    }
  }

  /// DELETE请求
  Future<ApiResponse<T>> delete<T>(
    String url, {
    Map<String, dynamic>? query,
    Map<String, String>? headers,
    bool requiresAuth = true,
  }) async {
    try {
      final response = await httpClient.delete(
        url,
        query: query,
        headers: _headers(customHeaders: headers),
      );
      
      return _handleResponse<T>(response);
    } on TimeoutException {
      return ApiResponse.error(
        status: ApiStatus.timeout,
        message: '请求超时',
      );
    } on SocketException {
      return ApiResponse.error(
        status: ApiStatus.noConnection,
        message: '网络连接错误',
      );
    } catch (e) {
      return ApiResponse.error(
        status: ApiStatus.failed,
        message: e.toString(),
      );
    }
  }
  
  /// 处理响应结果
  ApiResponse<T> _handleResponse<T>(Response response) {
    try {
      // 检查是否为成功响应
      if (response.isOk) {
        // 空响应处理
        if (response.body == null) {
          return ApiResponse.success(data: null);
        }
        
        // JSON响应处理
        return ApiResponse.success(
          data: response.body is T ? response.body as T : response.body,
        );
      }
      
      // 错误响应处理
      return _handleErrorResponse<T>(response);
    } catch (e) {
      // 解析错误处理
      return ApiResponse.error(
        status: ApiStatus.parseError,
        message: '响应解析失败: ${e.toString()}',
        statusCode: response.statusCode,
      );
    }
  }
  
  /// 处理错误响应
  ApiResponse<T> _handleErrorResponse<T>(Response response) {
    // 获取状态码
    final statusCode = response.statusCode;
    
    // 获取错误消息
    String errorMessage = '请求失败';
    if (response.body != null) {
      try {
        final body = response.body;
        if (body is Map<String, dynamic>) {
          errorMessage = body['message'] ?? errorMessage;
        } else if (body is String) {
          final decodedBody = jsonDecode(body);
          if (decodedBody is Map<String, dynamic>) {
            errorMessage = decodedBody['message'] ?? errorMessage;
          }
        }
      } catch (_) {
        // 无法解析错误消息
      }
    }
    
    // 根据状态码返回对应的API状态
    ApiStatus status;
    switch (statusCode) {
      case 400:
        status = ApiStatus.badRequest;
        break;
      case 401:
        status = ApiStatus.unauthorized;
        break;
      case 403:
        status = ApiStatus.forbidden;
        break;
      case 404:
        status = ApiStatus.notFound;
        break;
      case 408:
        status = ApiStatus.timeout;
        break;
      case 500:
      case 501:
      case 502:
      case 503:
        status = ApiStatus.serverError;
        break;
      default:
        status = ApiStatus.failed;
    }
    
    return ApiResponse.error(
      status: status,
      message: errorMessage,
      statusCode: statusCode,
    );
  }
} 